/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package br.ufrn.dimap.Grafo;

import br.ufrn.dimap.Conexao.FBConnection;
import br.ufrn.dimap.Grafo.excecoes.*;
import br.ufrn.dimap.Visitors.*;
import br.ufrn.dimap.arquivo.ArquivoDAO;
import br.ufrn.dimap.contagem.UsuarioPostSugestao;
import br.ufrn.dimap.interfaceGrafica.BuscaFlooders;
import br.ufrn.dimap.interfaceGrafica.JanelaPrincipal;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.swing.DefaultListModel;

/**
 *
 * @author augusto
 */
public class GrafoFBAPI {
    
    private FBConnection fb = null;
    private Rede grafo ;
    private boolean conexao = false;
    private BuscaPalavraVisitor v = null;
    
    public void metodoMilagroso (Usuario usuario)
    {
        try {
            grafo.inserirUsuario(usuario);
            List<Usuario> amigos = fb.getFriendsLista(usuario.getId());
            Iterator<Usuario> i = amigos.iterator();
            Usuario u;
            while (i.hasNext())
            {
                u = i.next();
                if(!grafo.existeUsuario(u.getId())){
                    try {
                        grafo.inserirUsuario(u);
                        //u = fb.getUserByName(u.getNome());
                        grafo.inserirRelacao(new Relacao(usuario, u));
                    } catch (ParDeUsuariosNaoExisteException ex) {
                        //Logger.getLogger(GrafoFBAPI.class.getName()).log(Level.SEVERE, null, ex);
                    }
                    metodoMilagroso(u);
                }
            }
        } catch (UsuarioJaExistenteException ex) {
            //Já existe rs
        } catch (RedeCheiaException ex) {
            //Logger.getLogger(GrafoFBAPI.class.getName()).log(Level.SEVERE, null, ex);
        } catch (TokenException ex) {
            
        }
    }
    
    public void metodoMilagroso (){
        metodoMilagroso(grafo.getRaiz());
    }
        
        
    public GrafoFBAPI(String at) throws  TokenException{
        try{
            fb = new FBConnection(at);
            grafo = new GrafoLista();
            grafo.setRaiz( fb.getUserByName("me"));
            //grafo.getDono().imprimirPost();
            conexao = true;
        }
        catch(Exception e){
            throw new TokenException();
        }
    }
    public GrafoFBAPI(){
        grafo = new GrafoLista();
    }
    
    public List<Usuario> getInfoBasicasAmigos() throws TokenException{
         List<Usuario> amigos;
        if(conexao == true){
            amigos = fb.getFriendsLista("me");
            atualizarAmigosGrafo(grafo.getRaiz(), amigos);
        }else{
            amigos = grafo.getAmigosLista(grafo.getRaiz());
        }
        
        return amigos;
    }
    
        public List<Usuario> getAmigos() throws TokenException{
         List<Usuario> amigos;
        if(conexao == true){
            amigos = fb.getFriendsLista("me");
            atualizarAmigosGrafo(grafo.getRaiz(), amigos);
        }else{
            amigos = grafo.getAmigosLista(grafo.getRaiz());
        }
        
        return amigos;
    }
    
    
    public List<Usuario> getAmigos(String nome) throws TokenException{
         List<Usuario> amigos;
         Usuario usuario = grafo.buscarUsuarioPorNome(nome);
         if(conexao == true){
            amigos = fb.getFriendsLista(usuario.getId());
            atualizarAmigosGrafo(usuario, amigos);
        }else{
            amigos = grafo.getAmigosLista(usuario);
        }
        return amigos;
    }
    
    public void salvarGrafo(){
        ArquivoDAO arq = new ArquivoDAO();
        arq.salvarGrafo(grafo, "grafo.txt");
    }

    public void abrirGrafo(){
        ArquivoDAO arq = new ArquivoDAO();
        this.grafo = arq.abrirGrafo("grafo.txt");
    }
    
    private void atualizarAmigosGrafo(Usuario usuario, List<Usuario> amigos) throws TokenException{
        try {
            grafo.inserirUsuario(usuario);
            Iterator<Usuario> itAmigos = amigos.iterator();
            int cont = 0;
            while(itAmigos.hasNext()){
                Usuario next = itAmigos.next();
                Usuario amigo;
                if(cont < amigos.size()){
                     amigo = fb.getUserByName(next.getId());
                     cont++;
                }
                else{
                    amigo = new Usuario(next.getId(), next.getNome());
                }
                grafo.inserirUsuario(amigo);
                grafo.inserirRelacao(new Relacao(usuario, amigo));
            }
        } catch (ParDeUsuariosNaoExisteException ex) {
            Logger.getLogger(JanelaPrincipal.class.getName()).log(Level.SEVERE, null, ex);
        } catch (UsuarioJaExistenteException ex) {
            Logger.getLogger(JanelaPrincipal.class.getName()).log(Level.SEVERE, null, ex);
        } catch (RedeCheiaException ex) {
            Logger.getLogger(JanelaPrincipal.class.getName()).log(Level.SEVERE, null, ex);
        }
        grafo.accept(new PrinterVisitor());
    }
    
    public String getUsuarioInfo(){
        
        return this.grafo.getRaiz().getInfo();
    }
    
    public String getInfoAmigo(String nome) throws TokenException{
       Usuario usuario = grafo.buscarUsuarioPorNome(nome);
       Usuario amigoUsuario;
       if(conexao == true && !usuario.temInfo()){
             amigoUsuario = fb.getUserByName(usuario.getId());
       }else{
             amigoUsuario = grafo.buscarUsuarioPorID(usuario.getId());
       }
       grafo.atualizarUsuario(amigoUsuario);
       amigoUsuario.accept(new PrinterVisitor());
       return amigoUsuario.getInfo();
    }    
    
    public List<String> getInfoAmigos() {
        grafo.accept(new PrinterVisitor());
        List<String> listaInfo = new ArrayList<String>();
        Iterator<Relacao> relacoes = grafo.obterRelacoes();
        while(relacoes.hasNext()){
            Relacao r = relacoes.next();
            listaInfo.add(r.getDestino().getInfo());
        }
        return listaInfo;
    }
    
    public void buscaLargura(Visitor v){
            grafo.buscaEmLargura(0, v);
    }
     
    public void buscaProfundidade(Visitor v){
            grafo.buscaEmProfundidade(0, v);
    }
    
    private void atualizarVisitor(String palavra)
    {
        if (v == null)
        {
            v = new BuscaPalavraVisitor(palavra, grafo.getAmigosLista(grafo.getRaiz()));
            grafo.accept(v);
            v.atualizar();
        }
    }
    
    public List<String> sugerirAmigos(String palavra){
        atualizarVisitor(palavra);
        
        ArrayList<UsuarioPostSugestao> as = v.getSugestoes(); 
        UsuarioPostSugestao u;
        ArrayList<String> sugestoes = new ArrayList();
        String aux;
        for (int i = 0; i < as.size(); i++)
        {
            u = as.get(i);
            aux = u.getNome() + " - " + u.getPontos();
            sugestoes.add(aux);
        }
        
        return sugestoes;
    }
    
    public List<String> topAmigosPalavra(String palavra){
        atualizarVisitor(palavra);
        
        ArrayList<UsuarioPostSugestao> as = v.getTopFriends(); 
        UsuarioPostSugestao u;
        ArrayList<String> topAmigos = new ArrayList();
        String aux;
        for (int i = 0; i < as.size(); i++)
        {
            u = as.get(i);
            aux = u.getNome() + " - " + u.getPontos();
            topAmigos.add(aux);
        }
        
        return topAmigos;
    }
    /*
    public void preencherGrafo(Usuario usuario, List<Usuario> listaAmigos) throws TokenException{
        Iterator<Usuario> amigos = listaAmigos.iterator();
        while(amigos.hasNext()){
             Usuario u = amigos.next();
             try{
                 this.getAmigos(u.getNome());
                 this.getInfoAmigo(u.getNome());
             }catch(TokenException t){
                try {
                    grafo.inserirRelacao(new Relacao(u, usuario));
                } catch (ParDeUsuariosNaoExisteException ex) {
                    Logger.getLogger(GrafoFBAPI.class.getName()).log(Level.SEVERE, null, ex);
                }
             }
        }
    }
    */
    public void preencherGrafo(List<Usuario> listaAmigos) throws TokenException{
        Iterator<Usuario> amigos = listaAmigos.iterator();
        int cont = 0;
        while(amigos.hasNext()){
             Usuario u = amigos.next();
             System.out.println(u.getNome());
             try{
                 this.getAmigos(u.getNome());
                 this.getInfoAmigo(u.getNome());
             }catch(TokenException t){
                 if(cont < 0){
                      this.getInfoAmigo(u.getNome());
                 }
                 cont++;
             }
        }
    }

    
    public String buscaFlooders(){
        AmigosFloodersVisitor af = new AmigosFloodersVisitor(grafo);
        grafo.accept(af);
        String result = af.getFlooder();
        return result;
    }
}
